home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / input / input_ext-intf.c < prev    next >
C/C++ Source or Header  |  2003-04-07  |  15KB  |  429 lines

  1. /*****************************************************************************
  2.  * input_ext-intf.c: services to the interface
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2001 VideoLAN
  5.  * $Id: input_ext-intf.c,v 1.48 2003/03/11 23:56:54 gbazin Exp $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23.  
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <string.h>                                    /* memcpy(), memset() */
  28.  
  29. #include <vlc/vlc.h>
  30.  
  31. #include "stream_control.h"
  32. #include "input_ext-dec.h"
  33. #include "input_ext-intf.h"
  34. #include "input_ext-plugins.h"
  35.  
  36. /*****************************************************************************
  37.  * input_SetStatus: change the reading status
  38.  *****************************************************************************/
  39. void __input_SetStatus( vlc_object_t * p_this, int i_mode )
  40. {
  41.     input_thread_t *p_input;
  42.  
  43.     p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
  44.  
  45.     if( p_input == NULL )
  46.     {
  47.         msg_Err( p_this, "no input found" );
  48.         return;
  49.     }
  50.  
  51.     vlc_mutex_lock( &p_input->stream.stream_lock );
  52.  
  53.     switch( i_mode )
  54.     {
  55.     case INPUT_STATUS_END:
  56.         p_input->stream.i_new_status = PLAYING_S;
  57.         p_input->b_eof = 1;
  58.         msg_Dbg( p_input, "end of stream" );
  59.         break;
  60.  
  61.     case INPUT_STATUS_PLAY:
  62.         p_input->stream.i_new_status = PLAYING_S;
  63.         msg_Dbg( p_input, "playing at normal rate" );
  64.         break;
  65.  
  66.     case INPUT_STATUS_PAUSE:
  67.         /* XXX: we don't need to check i_status, because input_clock.c
  68.          * does it for us */
  69.         p_input->stream.i_new_status = PAUSE_S;
  70.         msg_Dbg( p_input, "toggling pause" );
  71.         break;
  72.  
  73.     case INPUT_STATUS_FASTER:
  74.         /* If we are already going too fast, go back to default rate */
  75.         if( p_input->stream.control.i_rate * 8 <= DEFAULT_RATE )
  76.         {
  77.             msg_Dbg( p_input, "can not play any faster" );
  78.         }
  79.         else
  80.         {
  81.             p_input->stream.i_new_status = FORWARD_S;
  82.             p_input->stream.i_new_rate =
  83.                                     p_input->stream.control.i_rate / 2;
  84.  
  85.             if ( p_input->stream.i_new_rate < DEFAULT_RATE )
  86.             {
  87.                 msg_Dbg( p_input, "playing at %i:1 fast forward",
  88.                      DEFAULT_RATE / p_input->stream.i_new_rate );
  89.             }
  90.             else if ( p_input->stream.i_new_rate > DEFAULT_RATE )
  91.             {
  92.                 msg_Dbg( p_input, "playing at 1:%i slow motion",
  93.                       p_input->stream.i_new_rate / DEFAULT_RATE );
  94.             }
  95.             else if ( p_input->stream.i_new_rate == DEFAULT_RATE )
  96.             {
  97.                 p_input->stream.i_new_status = PLAYING_S;
  98.                 msg_Dbg( p_input, "playing at normal rate" );
  99.             }
  100.         }
  101.         break;
  102.  
  103.     case INPUT_STATUS_SLOWER:
  104.         /* If we are already going too slow, go back to default rate */
  105.         if( p_input->stream.control.i_rate >= 8 * DEFAULT_RATE )
  106.         {
  107.             msg_Dbg( p_input, "can not play any slower" );
  108.         }
  109.         else
  110.         {
  111.             p_input->stream.i_new_status = FORWARD_S;
  112.             p_input->stream.i_new_rate =
  113.                                     p_input->stream.control.i_rate * 2;
  114.  
  115.             if ( p_input->stream.i_new_rate < DEFAULT_RATE )
  116.             {
  117.                 msg_Dbg( p_input, "playing at %i:1 fast forward",
  118.                      DEFAULT_RATE / p_input->stream.i_new_rate );
  119.             }
  120.             else if ( p_input->stream.i_new_rate > DEFAULT_RATE )
  121.             {
  122.                 msg_Dbg( p_input, "playing at 1:%i slow motion",
  123.                       p_input->stream.i_new_rate / DEFAULT_RATE );
  124.             }
  125.             else if ( p_input->stream.i_new_rate == DEFAULT_RATE )
  126.             {
  127.                 p_input->stream.i_new_status = PLAYING_S;
  128.                 msg_Dbg( p_input, "playing at normal rate" );
  129.             }
  130.         }
  131.         break;
  132.  
  133.     default:
  134.         break;
  135.     }
  136.  
  137.     vlc_cond_signal( &p_input->stream.stream_wait );
  138.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  139.  
  140.     vlc_object_release( p_input );
  141. }
  142.  
  143. /*****************************************************************************
  144.  * input_Seek: changes the stream postion
  145.  *****************************************************************************/
  146. void __input_Seek( vlc_object_t * p_this, off_t i_position, int i_whence )
  147. {
  148.     input_thread_t *p_input;
  149.  
  150.     char psz_time1[OFFSETTOTIME_MAX_SIZE];
  151.     char psz_time2[OFFSETTOTIME_MAX_SIZE];
  152.  
  153.     p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
  154.  
  155.     if( p_input == NULL )
  156.     {
  157.         msg_Err( p_this, "no input found" );
  158.         return;
  159.     }
  160.  
  161.     vlc_mutex_lock( &p_input->stream.stream_lock );
  162.  
  163. #define A p_input->stream.p_selected_area
  164.     switch( i_whence & 0x30 )
  165.     {
  166.         case INPUT_SEEK_SECONDS:
  167.             i_position *= (off_t)50 * p_input->stream.i_mux_rate;
  168.             break;
  169.  
  170.         case INPUT_SEEK_PERCENT:
  171.             i_position = A->i_size * i_position / (off_t)100;
  172.             break;
  173.  
  174.         case INPUT_SEEK_BYTES:
  175.         default:
  176.             break;
  177.     }
  178.  
  179.     switch( i_whence & 0x03 )
  180.     {
  181.         case INPUT_SEEK_CUR:
  182.             A->i_seek = A->i_tell + i_position;
  183.             break;
  184.  
  185.         case INPUT_SEEK_END:
  186.             A->i_seek = A->i_size + i_position;
  187.             break;
  188.  
  189.         case INPUT_SEEK_SET:
  190.         default:
  191.             A->i_seek = i_position;
  192.             break;
  193.     }
  194.  
  195.     if( A->i_seek < 0 )
  196.     {
  197.         A->i_seek = 0;
  198.     }
  199.     else if( A->i_seek > A->i_size )
  200.     {
  201.         A->i_seek = A->i_size;
  202.     }
  203.  
  204.     msg_Dbg( p_input, "seeking position "I64Fd"/"I64Fd" (%s/%s)",
  205.              A->i_seek, A->i_size,
  206.              input_OffsetToTime( p_input, psz_time1, i_position ),
  207.              input_OffsetToTime( p_input, psz_time2, A->i_size ) );
  208. #undef A
  209.  
  210.     vlc_cond_signal( &p_input->stream.stream_wait );
  211.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  212.  
  213.     vlc_object_release( p_input );
  214. }
  215.  
  216. /*****************************************************************************
  217.  * input_Tell: requests the stream postion
  218.  *****************************************************************************/
  219. void __input_Tell( vlc_object_t * p_this, stream_position_t * p_position )
  220. {
  221.     input_thread_t *p_input;
  222.  
  223.     p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
  224.  
  225.     if( p_input == NULL )
  226.     {
  227.         p_position->i_tell = 0;
  228.         p_position->i_size = 0;
  229.         p_position->i_mux_rate = 0;
  230.         msg_Err( p_this, "no input found" );
  231.         return;
  232.     }
  233.  
  234.     vlc_mutex_lock( &p_input->stream.stream_lock );
  235.  
  236. #define A p_input->stream.p_selected_area
  237.     p_position->i_tell = A->i_tell;
  238.     p_position->i_size = A->i_size;
  239.     p_position->i_mux_rate = p_input->stream.i_mux_rate;
  240. #undef A
  241.  
  242.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  243.     vlc_object_release( p_input );
  244. }
  245.  
  246. /*****************************************************************************
  247.  * input_OffsetToTime : converts an off_t value to a time indicator, using
  248.  *                      mux_rate
  249.  *****************************************************************************
  250.  * BEWARE : this function assumes that you already own the lock on
  251.  * p_input->stream.stream_lock
  252.  *****************************************************************************/
  253. char * input_OffsetToTime( input_thread_t * p_input, char * psz_buffer,
  254.                            off_t i_offset )
  255. {
  256.     mtime_t         i_seconds;
  257.  
  258.     if( p_input->stream.i_mux_rate )
  259.     {
  260.         i_seconds = i_offset / 50 / p_input->stream.i_mux_rate;
  261.         snprintf( psz_buffer, OFFSETTOTIME_MAX_SIZE, "%d:%02d:%02d",
  262.                  (int) (i_seconds / (60 * 60)),
  263.                  (int) (i_seconds / 60 % 60),
  264.                  (int) (i_seconds % 60) );
  265.         return( psz_buffer );
  266.     }
  267.     else
  268.     {
  269.         /* Divide by zero is not my friend. */
  270.         sprintf( psz_buffer, "-:--:--" );
  271.         return( psz_buffer );
  272.     }
  273. }
  274.  
  275. /*****************************************************************************
  276.  * input_DumpStream: dumps the contents of a stream descriptor
  277.  *****************************************************************************
  278.  * BEWARE : this function assumes that you already own the lock on
  279.  * p_input->stream.stream_lock
  280.  *****************************************************************************/
  281. void input_DumpStream( input_thread_t * p_input )
  282. {
  283.     char psz_time1[OFFSETTOTIME_MAX_SIZE];
  284.     char psz_time2[OFFSETTOTIME_MAX_SIZE];
  285.     unsigned int i, j;
  286.  
  287. #define S   p_input->stream
  288.     msg_Dbg( p_input, "dumping stream ID 0x%x [OK:%ld/D:%ld]", S.i_stream_id,
  289.              S.c_packets_read, S.c_packets_trashed );
  290.     if( S.b_seekable )
  291.         msg_Dbg( p_input, "seekable stream, position: "I64Fd"/"I64Fd" (%s/%s)",
  292.                  S.p_selected_area->i_tell, S.p_selected_area->i_size,
  293.                  input_OffsetToTime( p_input, psz_time1,
  294.                                      S.p_selected_area->i_tell ),
  295.                  input_OffsetToTime( p_input, psz_time2,
  296.                                      S.p_selected_area->i_size ) );
  297.     else
  298.         msg_Dbg( p_input, "pace %scontrolled", S.b_pace_control ? "" : "un-" );
  299. #undef S
  300.     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
  301.     {
  302. #define P   p_input->stream.pp_programs[i]
  303.         msg_Dbg( p_input, "dumping program 0x%x, version %d (%s)",
  304.                  P->i_number, P->i_version,
  305.                  P->b_is_ok ? "complete" : "partial" );
  306. #undef P
  307.         for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
  308.         {
  309. #define ES  p_input->stream.pp_programs[i]->pp_es[j]
  310.             msg_Dbg( p_input, "ES 0x%x, "
  311.                      "stream 0x%x, fourcc `%4.4s', %s [OK:%ld/ERR:%ld]",
  312.                      ES->i_id, ES->i_stream_id, (char*)&ES->i_fourcc,
  313.                      ES->p_decoder_fifo != NULL ? "selected" : "not selected",
  314.                      ES->c_packets, ES->c_invalid_packets );
  315. #undef ES
  316.         }
  317.     }
  318. }
  319.  
  320. /*****************************************************************************
  321.  * input_ToggleES: answers to a user request with calls to (Un)SelectES
  322.  *****************************************************************************
  323.  * Useful since the interface plugins know p_es.
  324.  * It only works for audio & spu ( to be sure nothing nasty is being done ).
  325.  * b_select is a boolean to know if we have to select or unselect ES
  326.  *****************************************************************************/
  327. int input_ToggleES( input_thread_t * p_input, es_descriptor_t * p_es,
  328.                     vlc_bool_t b_select )
  329. {
  330.     vlc_mutex_lock( &p_input->stream.stream_lock );
  331.  
  332.     if( p_es != NULL )
  333.     {
  334.         if( b_select )
  335.         {
  336.             p_input->stream.p_newly_selected_es = p_es;
  337.         }
  338.         else
  339.         {
  340.             p_input->stream.p_removed_es = p_es;
  341.         }
  342.     }
  343.  
  344.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  345.  
  346.     return 0;
  347. }
  348.  
  349. /****************************************************************************
  350.  * input_ChangeArea: interface request an area change
  351.  ****************************************************************************/
  352. int input_ChangeArea( input_thread_t * p_input, input_area_t * p_area )
  353. {
  354.     vlc_mutex_lock( &p_input->stream.stream_lock );
  355.  
  356.     p_input->stream.p_new_area = p_area;
  357.  
  358.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  359.  
  360.     return 0;
  361. }
  362.  
  363. /****************************************************************************
  364.  * input_ChangeProgram: interface request a program change
  365.  ****************************************************************************/
  366. int input_ChangeProgram( input_thread_t * p_input, uint16_t i_program_number )
  367. {
  368.     pgrm_descriptor_t *       p_program;
  369.     vlc_value_t val;
  370.  
  371.     vlc_mutex_lock( &p_input->stream.stream_lock );
  372.  
  373.     p_program = input_FindProgram( p_input, i_program_number );
  374.  
  375.     if ( p_program == NULL )
  376.     {
  377.         msg_Err( p_input, "could not find selected program" );
  378.         return -1;
  379.     }
  380.  
  381.     p_input->stream.p_new_program = p_program;
  382.  
  383.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  384.  
  385.     /* Update the navigation variables without triggering a callback */
  386.     val.i_int = i_program_number;
  387.     var_Change( p_input, "program", VLC_VAR_SETVALUE, &val );
  388.  
  389.     return 0;
  390. }
  391.  
  392. /****************************************************************************
  393.  * input_ToggleGrayscale: change to grayscale or color output
  394.  ****************************************************************************/
  395. int input_ToggleGrayscale( input_thread_t * p_input )
  396. {
  397.     /* No need to warn the input thread since only the decoders and outputs
  398.      * worry about it. */
  399.     vlc_mutex_lock( &p_input->stream.control.control_lock );
  400.     p_input->stream.control.b_grayscale =
  401.                     !p_input->stream.control.b_grayscale;
  402.  
  403.     msg_Dbg( p_input, "changing to %s output",
  404.              p_input->stream.control.b_grayscale ? "grayscale" : "color" );
  405.  
  406.     vlc_mutex_unlock( &p_input->stream.control.control_lock );
  407.  
  408.     return 0;
  409. }
  410.  
  411. /****************************************************************************
  412.  * input_ToggleMute: activate/deactivate mute mode
  413.  ****************************************************************************/
  414. int input_ToggleMute( input_thread_t * p_input )
  415. {
  416.     /* We need to feed the decoders with 0, and only input can do that, so
  417.      * pass the message to the input thread. */
  418.     vlc_mutex_lock( &p_input->stream.stream_lock );
  419.     p_input->stream.b_new_mute = !p_input->stream.control.b_mute;
  420.  
  421.     msg_Dbg( p_input, "%s mute mode",
  422.              p_input->stream.control.b_mute ? "activating" : "deactivating" );
  423.  
  424.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  425.  
  426.     return 0;
  427. }
  428.  
  429.